package com.sayyi.demo.micro.order.config;

import io.seata.saga.engine.StateMachineEngine;
import io.seata.saga.engine.config.DbStateMachineConfig;
import io.seata.saga.engine.impl.ProcessCtrlStateMachineEngine;
import io.seata.saga.rm.StateMachineEngineHolder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.scheduling.concurrent.ThreadPoolExecutorFactoryBean;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class SagaStateMachineEngineConfig {

    @Bean
    public ThreadPoolExecutorFactoryBean threadExecutor() {
        ThreadPoolExecutorFactoryBean factoryBean = new ThreadPoolExecutorFactoryBean();
        factoryBean.setThreadNamePrefix("SAGA_ASYNC_EXE");
        factoryBean.setCorePoolSize(1);
        factoryBean.setMaxPoolSize(20);
        return factoryBean;
    }

    @Value("${seata.tx-service-group}")
    private String seataTxGroup;
    @Value("${spring.application.name}")
    private String applicationId;

    @Bean
    public DbStateMachineConfig dbStateMachineConfig(DataSource dataSource, ThreadPoolExecutorFactoryBean factoryBean) throws IOException {
        DbStateMachineConfig dbStateMachineConfig = new DbStateMachineConfig();
        dbStateMachineConfig.setDataSource(dataSource);
        dbStateMachineConfig.setThreadPoolExecutor((ThreadPoolExecutor) factoryBean.getObject());
        dbStateMachineConfig.setResources(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:statelang/*.json"));
        dbStateMachineConfig.setEnableAsync(true);
        dbStateMachineConfig.setTxServiceGroup(seataTxGroup);
        dbStateMachineConfig.setApplicationId(applicationId);
        return dbStateMachineConfig;
    }

    @Bean
    public ProcessCtrlStateMachineEngine stateMachineEngine(DbStateMachineConfig dbStateMachineConfig) {
        ProcessCtrlStateMachineEngine engine = new ProcessCtrlStateMachineEngine();
        engine.setStateMachineConfig(dbStateMachineConfig);
        return engine;
    }

    @Bean
    public StateMachineEngineHolder stateMachineEngineHolder(StateMachineEngine stateMachineEngine) {
        StateMachineEngineHolder engineHolder = new StateMachineEngineHolder();
        engineHolder.setStateMachineEngine(stateMachineEngine);
        return engineHolder;
    }
}
